#include <iostream>
#include <bits/allocator.h>
#include <vector>
#include <string>
#include <iterator>
#include <list>


using namespace std;

template<typename T>
typename T::value_type top(const T &c)
{
    if (!c.empty()) {
        cout <<  "=========" <<__LINE__ << endl;
        return c.back();
    } else{
        return typename T::value_type();
    }
}

struct Foo
{
    Foo() {}
public:
    int a, b ,c;
};

    /**
     * 为了解决 传入的 iterator 是 class 还是 pointer，
     *  下面制定了泛化版本 iterator_traits 和 偏特化版本 iterator_traits
*/
namespace my {
    template <class T >     //如果 T 是 class iterator
    struct iterator_traits {
        typedef typename T::value_type value_type;
    };

    template <class T>  //如果 T 是 pointer to T
    struct iterator_traits<T*> {
        typedef T value_type;
    };

    template <class T>  //如果 T 是 pointer to const T
    struct iterator_traits<const T*> {
        typedef T value_type;
    };

    /**
      其中的类型T 必须实现 iterator，上方的自定义Foo 就无法使用
      当想知道 T 的 value_type 时便可这么写
      template<typename T>
      void algorithm() {
        typename iterator_traits<T>::value_type v1;
      }
*/
}

//typename iterator_traits<T>::value_type a; 即可知晓T  的类型

void fun(int ){    cout << "int" <<endl; }
void fun(double ){    cout << "float" <<endl; }
void fun(char ){    cout << "char" <<endl; }
void fun(char* ){    cout << "char*" <<endl; }

int main()
{

    vector<int> vec;
    vec.push_back(1);
    vec.push_back(2);
    vec.push_back(3);

//    cout << top<vector<int> >(vec) << endl;

    vector<Foo> vec2;

//    cout << top<vector<Foo> > (vec2) <<endl;
    cout << sizeof(top<vector<Foo> > (vec2)) <<endl;

    iterator_traits<vector<int>::iterator>::value_type a;
    iterator_traits<vector<double>::iterator>::value_type b;
    iterator_traits<char*>::value_type c;

    vector<int>::iterator * pVecIt;
    list<int>::iterator * pListIt;


    typename vector<int>::iterator vecIt;
    typename vector<int>::iterator::value_type aa ;

//    vecIt::value_type ;
//    pVecIt->value_type;

    fun(a);
    fun(b);
    fun(c);


    return 0;
}
